/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.zhpan.bannerview.drawer;

import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

import com.zhpan.bannerview.options.IndicatorOptions;
import com.zhpan.bannerview.options.Options;
import com.zhpan.bannerview.utils.ArgbEvaluator;
import com.zhpan.bannerview.utils.IndicatorUtils;

/**
 * RectDrawer
 *
 * @since 2021-03-24
 */
public class RectDrawer extends BaseDrawer {
    /**
     * mRectF
     */
    protected final RectFloat mRectF = new RectFloat();

    /**
     * RectDrawer
     *
     * @param options 參數
     */
    public RectDrawer(IndicatorOptions options) {
        super(options);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        int pageSize = mOptions.getPageSize();
        if (pageSize > 1) {
            int slideMode = mOptions.getSlideMode();

            if (slideMode == Options.IndicatorMode.NORMAL) {
                drawInequalitySlider(canvas, pageSize);
                return;
            }

            if (slideMode == Options.IndicatorMode.SCALE) {
                for (int i = 0; i < pageSize; i++) {
                    drawScaleSlider(canvas, i);
                }
                return;
            }

            drawUncheckedSlider(canvas, pageSize);
            drawCheckedSlider(canvas);
        }
    }

    /**
     * drawDash
     *
     * @param canvas 參數
     */
    protected void drawDash(Canvas canvas) {
        // do noting
    }

    /**
     * drawScaleSlider
     *
     * @param canvas 參數
     * @param index 參數
     */
    private void drawScaleSlider(Canvas canvas, int index) {
        float indicatorGap = mOptions.getSliderGap();
        float sliderHeight = mOptions.getSliderHeight();
        int currentPosition = mOptions.getCurrentPosition();
        float normalWidth = mOptions.getNormalSliderWidth();
        float checkedWidth = mOptions.getCheckedSliderWidth();
        if (mOptions.getSlideProgress() == 1.0) {
            mOptions.setSlideProgress(0.999f);
        }
        Color checkedColor = mOptions.getCheckedSliderColor();
        Color normaColor = mOptions.getNormalSliderColor();
        if (index < currentPosition) {
            mPaint.setColor(normaColor);
            float left;
            if (currentPosition == mOptions.getPageSize() - 1) {
                left = (index * normalWidth + index * indicatorGap)
                    + (checkedWidth - normalWidth) * mOptions.getSlideProgress();
            } else {
                left = index * normalWidth + index * indicatorGap;
            }
            mRectF.modify(left, 0f, left + normalWidth, sliderHeight);
            drawRoundRect(canvas, sliderHeight, sliderHeight);
        } else if (index == currentPosition) {
            drawScaleSliderView(checkedColor,currentPosition,
                normaColor,normalWidth,checkedWidth, sliderHeight,canvas,index,indicatorGap);
        } else {
            if ((currentPosition + 1 != index || mOptions.getSlideProgress() == 0f)) { // 避免多余绘制
                mPaint.setColor(normaColor);
                float left = index * minWidth + index * indicatorGap + (checkedWidth - minWidth);
                mRectF.modify(left, 0f, left + minWidth, sliderHeight);
                drawRoundRect(canvas, sliderHeight, sliderHeight);
            }
        }
    }

    /**
     * drawScaleSliderView
     *
     * @param checkedColor 参数
     * @param currentPosition 参数
     * @param normaColor 参数
     * @param normalWidth 参数
     * @param checkedWidth 参数
     * @param sliderHeight 参数
     * @param canvas 参数
     * @param index 参数
     * @param indicatorGap 参数
     */
    private void drawScaleSliderView(Color checkedColor,
                                         int currentPosition,Color normaColor,float normalWidth, float checkedWidth,
                                         float sliderHeight,Canvas canvas, int index,float indicatorGap){
        mPaint.setColor(checkedColor);
        float slideProgress = mOptions.getSlideProgress();
        if (currentPosition == mOptions.getPageSize() - 1) {
            int evaluate = (int) ArgbEvaluator.evaluate(slideProgress,
                checkedColor.getValue(), normaColor.getValue());
            mPaint.setColor(new Color(evaluate));
            float right = (mOptions.getPageSize() - 1) * (normalWidth + mOptions.getSliderGap()) + checkedWidth;
            float left = right - checkedWidth + (checkedWidth - normalWidth) * slideProgress;
            mRectF.modify(left, 0f, right, sliderHeight);
            drawRoundRect(canvas, sliderHeight, sliderHeight);
        } else {
            if (slideProgress < 1) {
                int evaluate = (int) ArgbEvaluator.evaluate(slideProgress,
                    checkedColor.getValue(), normaColor.getValue());
                mPaint.setColor(new Color(evaluate));
                float left = index * normalWidth + index * indicatorGap;
                float right = left + normalWidth + (checkedWidth - normalWidth) * (1 - slideProgress);
                mRectF.modify(left, 0f, right, sliderHeight);
                drawRoundRect(canvas, sliderHeight, sliderHeight);
            }
        }
        if (currentPosition == mOptions.getPageSize() - 1) {
            if (slideProgress > 0) {
                int evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress,
                    checkedColor.getValue(), normaColor.getValue());
                mPaint.setColor(new Color(evaluate));
                float left = 0f;
                float right = left + normalWidth + (checkedWidth - normalWidth) * slideProgress;
                mRectF.modify(left, 0f, right, sliderHeight);
                drawRoundRect(canvas, sliderHeight, sliderHeight);
            }
        } else {
            if (slideProgress > 0) {
                int evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress,
                    checkedColor.getValue(), normaColor.getValue());
                mPaint.setColor(new Color(evaluate));
                float right = index * normalWidth + index * indicatorGap
                    + normalWidth + (indicatorGap + checkedWidth);
                float left = right - normalWidth - (checkedWidth - normalWidth) * slideProgress;
                mRectF.modify(left, 0f, right, sliderHeight);
                drawRoundRect(canvas, sliderHeight, sliderHeight);
            }
        }
    }

    /**
     * drawRoundRect
     *
     * @param canvas 參數
     * @param sliderHeight 參數
     * @param sliderHeight1 參數
     */
    protected void drawRoundRect(Canvas canvas, float sliderHeight, float sliderHeight1) {
        drawDash(canvas);
    }

    private void drawCheckedSlider(Canvas canvas) {
        mPaint.setColor(mOptions.getCheckedSliderColor());
        int slideMode = mOptions.getSlideMode();
        switch (slideMode) {
            case Options.IndicatorMode.SMOOTH:
                drawSmoothSlider(canvas);
                break;
            case Options.IndicatorMode.WORM:
                drawWormSlider(canvas);
                break;
            case Options.IndicatorMode.COLOR:
                drawColorSlider(canvas);
                break;
            default:
                break;
        }
    }

    private void drawColorSlider(Canvas canvas) {
        int currentPosition = mOptions.getCurrentPosition();
        float slideProgress = mOptions.getSlideProgress();
        float left = currentPosition * minWidth + currentPosition * mOptions.getSliderGap();
        if (slideProgress < 0.99) {
            int evaluate = (int) ArgbEvaluator.evaluate(slideProgress,
                mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
            mPaint.setColor(new Color(evaluate));
            mRectF.modify(left, 0f, left + minWidth, mOptions.getSliderHeight());
            drawRoundRect(canvas, mOptions.getSliderHeight(), mOptions.getSliderHeight());
        }

        float nextSliderLeft = left + mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
        if (currentPosition == mOptions.getPageSize() - 1) {
            nextSliderLeft = 0f;
        }
        int evaluate = (int) ArgbEvaluator.evaluate(1 - slideProgress,
            mOptions.getCheckedSliderColor().getValue(), mOptions.getNormalSliderColor().getValue());
        mPaint.setColor(new Color(evaluate));
        mRectF.modify(nextSliderLeft, 0f, nextSliderLeft + minWidth, mOptions.getSliderHeight());
        drawRoundRect(canvas, mOptions.getSliderHeight(), mOptions.getSliderHeight());
    }

    private void drawWormSlider(Canvas canvas) {
        float sliderHeight = mOptions.getSliderHeight();
        float slideProgress = mOptions.getSlideProgress();
        int currentPosition = mOptions.getCurrentPosition();
        float distance = mOptions.getSliderGap() + mOptions.getNormalSliderWidth();
        float startCoordinateX = IndicatorUtils.getCoordinateX(mOptions, maxWidth, currentPosition);
        float left = startCoordinateX + coerceAtLeast((distance * (slideProgress - 0.5f) * 2.0f), 0f)
            - mOptions.getNormalSliderWidth() / 2;
        float right = startCoordinateX + coerceAtMost((distance * slideProgress * 2f), distance)
            + mOptions.getNormalSliderWidth() / 2;
        mRectF.modify(left, 0f, right, sliderHeight);
        drawRoundRect(canvas, sliderHeight, sliderHeight);
    }

    private void drawSmoothSlider(Canvas canvas) {
        float currentPosition = mOptions.getCurrentPosition();
        float indicatorGap = mOptions.getSliderGap();
        float sliderHeight = mOptions.getSliderHeight();
        float left = currentPosition * maxWidth + currentPosition * +indicatorGap + (maxWidth + indicatorGap) * mOptions.getSlideProgress();
        mRectF.modify(left, 0f, left + maxWidth, sliderHeight);
        drawRoundRect(canvas, sliderHeight, sliderHeight);
    }

    private void drawUncheckedSlider(Canvas canvas, int pageSize) {
        for (int i = 0; i < pageSize; i++) {
            mPaint.setColor(mOptions.getNormalSliderColor());
            float left = i * maxWidth + i * +mOptions.getSliderGap() + (maxWidth - minWidth);
            mRectF.modify(left, 0f, left + minWidth, mOptions.getSliderHeight());
            drawRoundRect(canvas, mOptions.getSliderHeight(), mOptions.getSliderHeight());
        }
    }

    private void drawInequalitySlider(Canvas canvas, int pageSize) {
        float left = 0f;
        float sliderWidth;
        int currentPosition = mOptions.getCurrentPosition();
        Color checkedSliderColor = mOptions.getCheckedSliderColor();
        Color normalSliderColor = mOptions.getNormalSliderColor();
        float sliderHeight = mOptions.getSliderHeight();
        for (int i = 0; i < pageSize; i++) {
            sliderWidth = currentPosition == i ? maxWidth : minWidth;
            Color color = i == currentPosition ? checkedSliderColor : normalSliderColor;
            mPaint.setColor(color);
            mRectF.modify(left, 0f, left + sliderWidth, mOptions.getSliderHeight());
            drawRoundRect(canvas, sliderHeight, sliderHeight);
            left += sliderWidth + mOptions.getSliderGap();
        }
    }
}
